const url = require('url');
const del = require('del');
const fs = require('fs-extra');
const _ = require('lodash');
const g = require('gulp');
const $ = require('gulp-load-plugins')();
const webpack = require("webpack");
const Server = require("webpack-dev-server");
const combine = require('stream-combiner');
const ws = require('webpack-stream');
const u = require('./gulp.util');
const cfg = require('./config');
const {log, colors} = $.util;

/////////////////////////////////////////////////////////////////////
// 文件复制

g.task('copy.bin', () => u.copyNew(
    u.dir(cfg.src.bin.dir),
    cfg.run.dir,
    {base: cfg.src.bin.dir}
));

g.task('copy.etc', () => u.copyNew(
    u.dir(cfg.src.etc.dir),
    cfg.run.dir,
    {base: cfg.src.dir}
));

g.task('copy.res', () => u.copyNew(
    u.dir(cfg.src.res.dir),
    cfg.run.web.dir,
    {base: cfg.src.res.dir}
));

g.task('copy.libs', () => {
    _.each(cfg.libs.copys, i => {
        const _src = `./node_modules/${i.from}`;
        const _dst = `./run/www/${i.to}`;
        fs.copy(_src, _dst, function (err) {
            if (err) return console.error(err, _src, _dst)
        });
    });
});

g.task('copy', ['copy.bin', 'copy.etc', 'copy.res']);

/////////////////////////////////////////////////////////////////////
// 前端编译

g.task('webpack', () => combine(
    g.src(cfg.src.web.entry),
    ws(require('./webpack.config')),
    g.dest(cfg.run.web.dir)
));

g.task('webpack.debug', (cb) => {
    const config = require('./webpack.debug');
    const compiler = webpack(config);

    compiler.plugin("compile", (/*params*/) => {
        log(colors.green('[webpack]'), "The compiler is starting to compile...");
    });
    compiler.plugin("compilation", (compilation) => {
        const {name} = compilation;
        log(colors.blue("The compiler is starting a new compilation..."), '[', colors.yellow(name), ']');
        compilation.plugin("optimize", () => {
            log(colors.cyan("The compilation is starting to optimize files..."), '[', colors.yellow(name), ']');
        });
    });
    compiler.plugin("emit", (compilation, callback) => {
        log(colors.green('[webpack]'), "The compilation is going to emit files...");
        callback();
    });

    const apiServer = url.format(_.omit(cfg.api, 'path'));
    new Server(compiler, {
        hot: true,
        historyApiFallback: true,
        publicPath: config.output.publicPath || '/',
        proxy: [{
            context: cfg.proxy.concat(cfg.api.path),
            target: apiServer
        }],
        stats: {
            colors: true,
            chunks: false,
            children: false
        }
    }).listen(cfg.port, err => {
        if (err) throw new $.util.PluginError('webpack-dev-server', err);
        log(colors.green('[webpack-dev-server]'), `running at ${cfg.port}`);
        cb();
    });
});

/////////////////////////////////////////////////////////////////////
// 后端编译

const babel_option = {
    presets: ['es2015']
};

g.task('build', ['check.app', 'check.etc'], () =>
    u.src(u.dir([cfg.src.app.dir], '.js'), {base: cfg.src.dir})
        .pipe($.babel(babel_option))
        .pipe(g.dest(cfg.run.dir))
);

g.task('clean', () => del(cfg.run.dir));

const cache = new $.cacheModified();

g.task('build.debug', ['check.app', 'check.etc'], () =>
    u.src(u.dir([cfg.src.app.dir], '.js'), {base: cfg.src.dir})
        .pipe(cache.updateSource())
        .pipe($.sourcemaps.init())
        .pipe($.babel(babel_option))
        .pipe(cache.updateProcessed())
        .pipe($.sourcemaps.write('.'))
        .pipe(g.dest(cfg.run.dir))
);

/////////////////////////////////////////////////////////////////////
// 调试运行

g.task('debug', ['build.debug'], () => $.nodemon({
    env: {NODE_ENV: 'development'},
    watch: [cfg.src.app.dir],
    tasks: 'build.debug',
    script: `${cfg.run.dir}/${cfg.main}`,
    nodeArgs: [`--debug=${cfg.debug || 5858}`],
    args: cfg.args
}));

g.task('watch', () => {
    g.watch(u.dir(cfg.src.etc.dir), ['copy.etc']);
    g.watch(u.dir(cfg.src.res.dir), ['copy.res']);
});
